// Created: Dec 14, 2014
//
// Author: wjinwen.1988@gmail.com

#ifndef CHI_NET_TCPCONNECTION_H
#define CHI_NET_TCPCONNECTION_H

#include <string>
#include <memory>

#include "chi/mutex.h"
#include "chi/net/buffer.h"
#include "chi/net/callbacks.h"
#include "chi/net/inet_address.h"

namespace chi {
namespace net {

class Channel;
class EventLoop;
class Socket;

// TCP connection, for both client and server usage.
class TcpConnection : public std::enable_shared_from_this<TcpConnection> {
 public:
  TcpConnection(EventLoop* loop,                  // 事件管理对象指针
                const std::string& name,          // 连接名
                int sockfd,                       // socket
                const InetAddress& local_addr,    // 本地地址
                const InetAddress& peer_addr      // 对端地址
                );
  virtual ~TcpConnection();

  TcpConnection(const TcpConnection& ) = delete;
  void operator=(const TcpConnection& ) = delete;
  
  // 获取事件管理对象指针
  EventLoop* loop() const { return loop_; }
  // 获取连接名
  const std::string& name() const { return name_; }
  // 获取本地地址
  const InetAddress& local_addr() const { return local_addr_; }
  // 获取对端地址
  const InetAddress& peer_addr() const { return peer_addr_; }
  // 获取连接状态 
  virtual bool connected() const { return state_ == StateE::kConnected; }

  // 发送消息
  // 线程安全，可以在任意地方调用。
  virtual void Send(const std::string& message);
  virtual void Send(const void* message, size_t len);
  virtual void Send(Buffer&& message);
  
  // 关闭连接
  // 线程安全
  void Shutdown();

  // 是否打开TCP_NODELAY模式.
  void SetTcpNoDelay(bool on);

  // 设置连接变化回调函数
  void set_connection_callback(const ConnectionCallback& cb);
  // 设置消息接收回调函数
  void set_message_callback(const MessageCallback& cb);
  // 设置连接断开回调函数
  // 内部调用。
  void set_close_callback(const CloseCallback& cb);
  
  // 当TcpServer accept一个新连接以后，调用此函数。
  // 只能调用一次。
  void ConnectionEstablished();
  // 当TcpServer从map中删除本连接时，调用此函数。
  // 只能调用一次。
  void ConnectDestroyed();
 protected:
  enum StateE { kDisconnected, kConnecting, kConnected, kDisconnecting };
   // socket可读回调
  virtual void HandleRead();
  // socket可写回调
  virtual void HandleWrite();
  // 连接端口回调
  virtual void HandleClose();
  // socket错误回调
  virtual void HandleError();

  // 把发送消息/关闭连接的动作放到EventLoop内执行，
  // 保证所有的操作都能在同一个线程内执行。
  virtual void SendInLoop(const std::string& message);
  virtual void RealSend(const void* data, size_t len);
  void ShutdownInLoop();
  void set_state(StateE s) { state_ = s; }

  EventLoop* loop_;         // libevent事件管理对象指针
  std::string name_;        // 连接名
  StateE state_;            // 连接状态
  Socket* socket_;          // Socket对象,持有当前连接的socket文件描述符。
  Channel* channel_;        // 连接通道，管理连接上所有的事件。
  InetAddress local_addr_;  // 本地地址
  InetAddress peer_addr_;   // 对端地址
  // 连接变化回调函数
  ConnectionCallback connection_callback_;
  // 消息可读回调函数
  MessageCallback message_callback_;
  // 连接关闭回调函数
  CloseCallback close_callback_;
  // 接收缓冲区
  Buffer input_buffer_;
  // 发送缓冲区
  Buffer output_buffer_;
};

typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;

}  
}

#endif
